﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;

namespace WCFMastering.Framework
{
   //T is the service contract and C is the callback contract
    public abstract class DuplexClientBase<T, C> : DuplexClientBase<T> where T : class
    {
        #region Ctors

        protected DuplexClientBase(InstanceContext<C> context)
            : base(context.Context)
        {
        }

        protected DuplexClientBase(InstanceContext<C> context, string endpointName) :
            base(context.Context, endpointName)
        {
        }

        protected DuplexClientBase(InstanceContext<C> context, Binding binding, EndpointAddress remoteAddress) :
            base(context.Context, binding, remoteAddress)
        {
        }

        protected DuplexClientBase(C callback)
            : base(callback)
        {
        }

        protected DuplexClientBase(C callback, string endpointName) :
            base(callback, endpointName)
        {
        }

        protected DuplexClientBase(C callback, Binding binding, EndpointAddress remoteAddress) :
            base(callback, binding, remoteAddress)
        {
        }

        #endregion 

        #region static ctor and verify method

        static DuplexClientBase()
        {
            VerifyCallback();
        }

        internal static void VerifyCallback()
        {
            Type contractType = typeof(T);
            Type callbackType = typeof(C);
            object[] attributes = contractType.GetCustomAttributes(
            typeof(ServiceContractAttribute), false);
            if (attributes.Length == 0)
            {
                throw new InvalidOperationException("Type of " + contractType +
                " is not a service contract");
            }
            ServiceContractAttribute serviceContractAttribute;
            serviceContractAttribute = attributes[0] as ServiceContractAttribute;
            if (callbackType != serviceContractAttribute.CallbackContract)
            {
                throw new InvalidOperationException("Type of " + callbackType +
                " is not configured as callback contract for " + contractType);
            }
        }

        #endregion
    }
}
